package com.hrma.services.impl;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.hrma.dao.*;
import com.hrma.entity.*;
import com.hrma.entity.exception.DataIsNull;
import com.hrma.services.WageStatisticService;
import org.springframework.stereotype.Service;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

@Service
public class WageStatisticImpl implements WageStatisticService {
    private final WageStatisticMapper wageStatisticMapper;
    private final PenaltyMapper penaltyMapper;
    private final RewardMapper rewardMapper;
    private final EmployeeMapper employeeMapper;
    private final AchievementMapper achievementMapper;
    private final AttendanceMapper attendanceMapper;

    public WageStatisticImpl(WageStatisticMapper wageStatisticMapper, PenaltyMapper penaltyMapper, RewardMapper rewardMapper, EmployeeMapper employeeMapper, AchievementMapper achievementMapper, AttendanceMapper attendanceMapper) {
        this.wageStatisticMapper = wageStatisticMapper;
        this.penaltyMapper = penaltyMapper;
        this.rewardMapper = rewardMapper;
        this.employeeMapper = employeeMapper;
        this.achievementMapper = achievementMapper;
        this.attendanceMapper = attendanceMapper;
    }

    @Override
    public Integer getPenaltyMoney(WageStatistic data) {
        List<Integer> penaltyMoney = penaltyMapper.getMoney(data);
        int penaltyCount = 0;
        for (Integer i : penaltyMoney) {
            penaltyCount += i;
        }
        return penaltyCount;
    }

    @Override
    public Integer getRewardMoney(WageStatistic data) {
        List<Integer> penaltyMoney = rewardMapper.getMoney(data);
        int rewardCount = 0;
        for (Integer i : penaltyMoney) {
            rewardCount += i;
        }
        return rewardCount;
    }

//    @Override
//    public Integer getAchievementMoney(WageStatistic data) {
//        List<Integer> achievementMoney = achievementMapper.getMoney(data);
//        int achievementCount = 0;
//        for (Integer i : achievementMoney) {
//            achievementCount += i;
//        }
//        return achievementCount;
//    }

    @Override
    public Integer getAttendancetMoney(WageStatistic data) {
        //获取员工考勤结果
        AttendanceResult attendanceResult = attendanceMapper.getAttendance(data);

        if(attendanceResult == null){
            throw new DataIsNull("考勤结果为空!");
        }
        if(attendanceResult.getLate() == null){
            throw new DataIsNull("迟到次数为空!");
        }
        if(attendanceResult.getLeaveEarly() == null){
            throw new DataIsNull("早退次数为空!");
        }
        if(attendanceResult.getAbsence() == null){
            throw new DataIsNull("缺勤次数为空!");
        }
        if(attendanceResult.getLeaveNum() == null){
            throw new DataIsNull("请假次数为空!");
        }
        //获取考勤扣款规则
        AttendanceRule attendanceRule = attendanceMapper.getAttendanceRule();
        //将Json格式规则转成AttendanceRuleVO对象
        ObjectMapper mapper = new ObjectMapper();
        mapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
        mapper.disable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
        AttendanceRuleVO attendanceRuleVO = new AttendanceRuleVO();
        try {
            attendanceRuleVO = mapper.readValue(attendanceRule.getRule(), AttendanceRuleVO.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        int attendanceCount = 0;

        //迟到扣款
        int lateMoney = 0;
        if(attendanceResult.getLate() != 0){
            for (int i = 0; i < attendanceResult.getLate(); i++) {
                if (i >= attendanceRuleVO.getLateMoney().size()) {
                    lateMoney += attendanceRuleVO.getLateMoney().get(attendanceRuleVO.getLateMoney().size() - 1).getMoney();
                }else{
                    lateMoney += attendanceRuleVO.getLateMoney().get(i).getMoney();
                }
            }
            lateMoney *= 100;
        }

        //早退扣款
        int leaveEarlyMoney = 0;
        if(attendanceResult.getLeaveEarly() != 0){
            for (int i = 0; i < attendanceResult.getLeaveEarly(); i++) {
                if (i >= attendanceRuleVO.getLeaveEarlyMoney().size()) {
                    leaveEarlyMoney += attendanceRuleVO.getLeaveEarlyMoney().get(attendanceRuleVO.getLeaveEarlyMoney().size() - 1).getMoney();
                }else {
                    leaveEarlyMoney += attendanceRuleVO.getLeaveEarlyMoney().get(i).getMoney();
                }
            }
            leaveEarlyMoney *= 100;
        }

        //日工资
        int dayMoney = (int)(employeeMapper.getSalary(data.getNum()) / 21.75 * 100);

        //缺勤扣款
        int absenceMoney = 0;
        if(attendanceResult.getAbsence() != 0){
            for (int i = 0; i < attendanceResult.getAbsence(); i++) {
                if (i >= attendanceRuleVO.getAbsenceMoney().size()) {
                    absenceMoney = absenceMoney + dayMoney * attendanceRuleVO.getAbsenceMoney().get(attendanceRuleVO.getAbsenceMoney().size() - 1).getMoney();
                }else{
                    absenceMoney = absenceMoney + dayMoney * attendanceRuleVO.getAbsenceMoney().get(i).getMoney();
                }
            }
        }

        //加班费
        int overtimeMoney = attendanceResult.getOvertime() * (dayMoney / 8);
        data.setOvertimeMoney(overtimeMoney);

        //请假减少的工资
        int leaveMoney = attendanceResult.getLeaveNum() * dayMoney;
        //考勤总扣款
        attendanceCount = absenceMoney + lateMoney + leaveMoney + leaveEarlyMoney;
        //是否有全勤奖
        if (attendanceCount == 0) {
            data.setPerfectAttendance(attendanceRuleVO.getPerfectAttendance() * 100);
        }else {
            data.setPerfectAttendance(0);
        }

        return attendanceCount;
    }

    @Override
    public void addAllEmployeeWage() {
        //上月第一天
        Calendar lastMonthFirstDateCal = Calendar.getInstance();
        lastMonthFirstDateCal.add(Calendar.MONTH, -1);
        lastMonthFirstDateCal.set(Calendar.MILLISECOND,0);
        int year = lastMonthFirstDateCal.get(Calendar.YEAR);
        int month = lastMonthFirstDateCal.get(Calendar.MONTH);
        lastMonthFirstDateCal.set(year,month,1,0,0,0);
        Date lastMonthFirstDate = lastMonthFirstDateCal.getTime();
        //本月第一天0点
        Calendar lastMonthEndDateCal = Calendar.getInstance();
        lastMonthEndDateCal.set(Calendar.MILLISECOND,0);
        int year1 = lastMonthEndDateCal.get(Calendar.YEAR);
        int month1 = lastMonthEndDateCal.get(Calendar.MONTH);
        lastMonthEndDateCal.set(year1,month1,1,0,0,0);
        Date lastMonthEndDate = lastMonthEndDateCal.getTime();
        //得到上月在职员工信息
        List<EmployeeVO> allemployee = employeeMapper.lastMonthAllNumAndSalary(lastMonthFirstDate,lastMonthEndDate);
        for (EmployeeVO i :
                allemployee) {
            //创建结果存储对象
            WageStatistic wageStatistic = new WageStatistic();
            wageStatistic.setNum(i.getNum());
            wageStatistic.setName(i.getName());
            wageStatistic.setBeginTime(lastMonthFirstDate);
            wageStatistic.setEndTime(lastMonthEndDate);
            int baseMoney = i.getMoney() * 100;
            wageStatistic.setBaseMoney(baseMoney);
            int postMoney = i.getPostMoney() * 100;
            wageStatistic.setPostMoney(postMoney);
            int rewardMoney = getPenaltyMoney(wageStatistic) * 100;
            int penaltyMoney = getRewardMoney(wageStatistic) * 100;
            int achievementMoney = achievementMapper.getMoney(wageStatistic) * 100;
            int attendanceDeduction = getAttendancetMoney(wageStatistic);
            if(attendanceDeduction >= baseMoney){
                attendanceDeduction = baseMoney;
            }
            wageStatistic.setRewardMoney(rewardMoney);
            wageStatistic.setPenaltyMoney(penaltyMoney);
            wageStatistic.setAchievementMoney(achievementMoney);
            wageStatistic.setAttendanceDeduction(attendanceDeduction);
            int wage = baseMoney + postMoney + rewardMoney - penaltyMoney + achievementMoney - attendanceDeduction + wageStatistic.getPerfectAttendance() + wageStatistic.getOvertimeMoney();
            if(wage < 0) {
                wage = 0;
            }
            wageStatistic.setWage(wage);
            wageStatisticMapper.add(wageStatistic);
        }
    }

    @Override
    public Page<WageStatisticResult> getList(WageStatisticDTO data) {
        PageHelper.startPage(data.getPageNum(), data.getPageSize());
        Page<WageStatistic> pageWageStatistic = wageStatisticMapper.getList(data);
        if(pageWageStatistic.isEmpty()){
            return null;
        }

        Page<WageStatisticResult> pageWageStaticResult = new Page<>();
        for (WageStatistic i : pageWageStatistic) {
            WageStatisticResult wageStaticResult = new WageStatisticResult();
            wageStaticResult.setId(i.getId());
            wageStaticResult.setNum(i.getNum());
            wageStaticResult.setName(i.getName());
            wageStaticResult.setBeginTime(i.getBeginTime());
            wageStaticResult.setEndTime(i.getEndTime());
            wageStaticResult.setBaseMoney(i.getBaseMoney() / 100.0);
            wageStaticResult.setRewardMoney(i.getRewardMoney() / 100.0);
            wageStaticResult.setPenaltyMoney(i.getPenaltyMoney() / 100.0);
            wageStaticResult.setAchievementMoney(i.getAchievementMoney() / 100.0);
            wageStaticResult.setAttendanceDeduction(i.getAttendanceDeduction() / 100.0);
            wageStaticResult.setPerfectAttendance(i.getPerfectAttendance() / 100.0);
            wageStaticResult.setPostMoney(i.getPostMoney() / 100.0);
            wageStaticResult.setOvertimeMoney(i.getOvertimeMoney() / 100.0);
            wageStaticResult.setWage(i.getWage() / 100.0);
            pageWageStaticResult.add(wageStaticResult);
        }

//        WageStatistic wageStatistic = pageWageStatistic.get(0);
//        wageStatistic.setBaseMoney(wageStatistic.getBaseMoney() / 100);
//        wageStatistic.setRewardMoney(wageStatistic.getRewardMoney() / 100);
//        wageStatistic.setPenaltyMoney(wageStatistic.getPenaltyMoney() / 100);
//        wageStatistic.setAchievementMoney(wageStatistic.getAchievementMoney() / 100);
//        wageStatistic.setAttendanceDeduction(wageStatistic.getAttendanceDeduction() / 100);
//        wageStatistic.setPerfectAttendance(wageStatistic.getPerfectAttendance() / 100);
//        wageStatistic.setPostMoney(wageStatistic.getPostMoney() / 100);
//        wageStatistic.setWage(wageStatistic.getWage() / 100);
//        pageWageStatistic.set(0,wageStatistic);
        return pageWageStaticResult;
    }

    @Override
    public void update(WageStatistic data) {
        if (!wageStatisticMapper.exist(data.getId())) {
            throw new RuntimeException("id字段不存在！");
        }
        wageStatisticMapper.update(data);
    }

    @Override
    public void delete(Integer id) {
        wageStatisticMapper.delete(id);
    }


}
